import { Col } from "./data_ext";
import SerializeAble, { c2n, n2c, Serialize, SerializeClass } from "./serialize";
import Utils from "./utils";

@SerializeClass("LibraryRecord")
export class LibraryRecord extends SerializeAble {
    @Serialize()
    key: string;
};

export class Library {
    private static __inited = false;
    private static __recordCol: Col<LibraryRecord> = {};
    static Init() {
        if (this.__inited) {
            return;
        }
        let allLibJas = Utils.loader.getAssets<cc.JsonAsset>("", "librarys", "cc.JsonAsset");
        allLibJas.forEach(ja => {
            if (typeof ja.json === "object" && ja.json instanceof Array) {
                ja.json.forEach((conf) => {
                    let confObj: LibraryRecord = this.__create(conf);
                    this.__recordCol[confObj.key] = confObj;
                });
            }
            else {
                let confObj: LibraryRecord = this.__create(ja.json);
                this.__recordCol[confObj.key] = confObj;
            }
        });
        this.__inited = true;
    }
    private static __create(conf: any) {
        if (conf.key) {
            console.warn("Library 注意: 有配置没有设置key成员", conf);
        }
        let ctor = n2c(conf["$cn"] || conf["__cn"]);
        let obj = new ctor();
        if (!(obj instanceof LibraryRecord)) {
            console.error(`Library 错误: ${c2n(ctor)} 类没有继承 LibraryRecord`);
        }
        obj.assignFromJSON(conf);
        return obj;
    }
    static GetRecordClassByKey(key: string) {
        if (!this.__inited) {
            this.Init();
        }
        let conf = this.__recordCol[key];
        return n2c(conf["$cn"]);
    }
    // ctor的作用是让 TS推算T类型.
    static GetRecord<T>(ctor: { prototype: T }, key: string) {
        if (!this.__inited) {
            this.Init();
        }
        return <T>this.__recordCol[key];
    }
    static CloneRecord<T>(ctor: { prototype: T }, key: string) {
        if (!this.__inited) {
            this.Init();
        }
        //@ts-ignore
        return <T>SerializeAble.CreateFromJSON(JSON.stringify(this.__recordCol[key]), ctor);
    }
    // 
    static GetRecords<T>(ctor: { prototype: T }) {
        if (!this.__inited) {
            this.Init();
        }

        //@ts-ignore
        let ctorName = c2n(ctor);

        let list = [];
        for (let key in this.__recordCol) {
            let rec = this.__recordCol[key];
            //@ts-ignore
            if (c2n(rec.constructor) == ctorName) {
                list.push(rec);
            }
        }
        return <T[]>list;
    }
    static SetRecord<T extends LibraryRecord>(record: T) {
        this.__recordCol[record.key] = record;
    }

};